package com.stx.jeepay.core.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.stx.jeepay.core.dao.PayOrderDao;
import com.stx.jeepay.core.dao.RefundOrderDao;
import com.stx.jeepay.core.entity.RefundOrderEntity;
import com.stx.jeepay.core.expection.BizException;
import com.stx.jeepay.core.service.RefundOrderService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;


@Service("refundOrderService")
public class RefundOrderServiceImpl extends ServiceImpl<RefundOrderDao, RefundOrderEntity> implements RefundOrderService {

    @Autowired
    private PayOrderDao payOrderDao;

    /**
     * 查询商户订单
     **/
    @Override
    public RefundOrderEntity queryMchOrder(String mchNo, String mchRefundNo, String refundOrderId) {
        if (StringUtils.isNotEmpty(refundOrderId)) {
            return getOne(new LambdaQueryWrapper<RefundOrderEntity>()
                    .eq(RefundOrderEntity::getMchNo, mchNo)
                    .eq(RefundOrderEntity::getRefundOrderId, refundOrderId));
        } else if (StringUtils.isNotEmpty(mchRefundNo)) {
            return getOne(new LambdaQueryWrapper<RefundOrderEntity>()
                    .eq(RefundOrderEntity::getMchNo, mchNo)
                    .eq(RefundOrderEntity::getMchRefundNo, mchRefundNo));
        } else {
            return null;
        }
    }

    /**
     * 更新退款单状态  【退款单生成】 --》 【退款中】
     **/
    @Override
    public boolean updateInit2Ing(String refundOrderId, String channelOrderId) {
        RefundOrderEntity updateOrder = new RefundOrderEntity();
        updateOrder.setState(RefundOrderEntity.STATE_ING);
        updateOrder.setChannelOrderNo(channelOrderId);

        return update(updateOrder, new LambdaUpdateWrapper<RefundOrderEntity>()
                .eq(RefundOrderEntity::getRefundOrderId, refundOrderId)
                .eq(RefundOrderEntity::getState, RefundOrderEntity.STATE_INIT));
    }

    /**
     * 更新退款单状态  【退款中】 --》 【退款成功/退款失败】
     **/
    @Override
    public boolean updateIng2SuccessOrFail(String refundOrderId, Byte updateState, String channelOrderNo,
                                           String channelErrCode, String channelErrMsg) {
        if (updateState == RefundOrderEntity.STATE_ING) {
            return true;
        } else if (updateState == RefundOrderEntity.STATE_SUCCESS) {
            return updateIng2Success(refundOrderId, channelOrderNo);
        } else if (updateState == RefundOrderEntity.STATE_FAIL) {
            return updateIng2Fail(refundOrderId, channelOrderNo, channelErrCode, channelErrMsg);
        }
        return false;
    }

    /**
     * 更新退款单状态  【退款中】 --》 【退款失败】
     **/
    @Transactional
    public boolean updateIng2Fail(String refundOrderId, String channelOrderNo, String channelErrCode, String channelErrMsg) {
        RefundOrderEntity updateOrder = new RefundOrderEntity();
        updateOrder.setState(RefundOrderEntity.STATE_FAIL);
        updateOrder.setErrCode(channelErrCode);
        updateOrder.setErrMsg(channelErrMsg);
        updateOrder.setChannelOrderNo(channelOrderNo);

        return update(updateOrder, new LambdaUpdateWrapper<RefundOrderEntity>()
                .eq(RefundOrderEntity::getRefundOrderId, refundOrderId)
                .eq(RefundOrderEntity::getState, RefundOrderEntity.STATE_ING));
    }

    /**
     * 更新退款单为 关闭状态
     **/
    @Override
    public int updateOrderExpired() {
        RefundOrderEntity refundOrder = new RefundOrderEntity();
        refundOrder.setState(RefundOrderEntity.STATE_CLOSED);

        return this.baseMapper.update(refundOrder, new LambdaQueryWrapper<RefundOrderEntity>()
                .in(RefundOrderEntity::getState, Arrays.asList(RefundOrderEntity.STATE_INIT, RefundOrderEntity.STATE_ING))
                .le(RefundOrderEntity::getExpiredTime, new Date()));
    }

    @Override
    public IPage<RefundOrderEntity> pageList(IPage iPage, LambdaQueryWrapper<RefundOrderEntity> queryWrapper, RefundOrderEntity refundOrder, JSONObject paramJSON) {
        if (StringUtils.isNotEmpty(refundOrder.getRefundOrderId())) {
            queryWrapper.eq(RefundOrderEntity::getRefundOrderId, refundOrder.getRefundOrderId());
        }
        if (StringUtils.isNotEmpty(refundOrder.getPayOrderId())) {
            queryWrapper.eq(RefundOrderEntity::getPayOrderId, refundOrder.getPayOrderId());
        }
        if (StringUtils.isNotEmpty(refundOrder.getChannelPayOrderNo())) {
            queryWrapper.eq(RefundOrderEntity::getChannelPayOrderNo, refundOrder.getChannelPayOrderNo());
        }
        if (StringUtils.isNotEmpty(refundOrder.getMchNo())) {
            queryWrapper.eq(RefundOrderEntity::getMchNo, refundOrder.getMchNo());
        }
        if (StringUtils.isNotEmpty(refundOrder.getIsvNo())) {
            queryWrapper.eq(RefundOrderEntity::getIsvNo, refundOrder.getIsvNo());
        }
        if (refundOrder.getMchType() != null) {
            queryWrapper.eq(RefundOrderEntity::getMchType, refundOrder.getMchType());
        }
        if (StringUtils.isNotEmpty(refundOrder.getMchRefundNo())) {
            queryWrapper.eq(RefundOrderEntity::getMchRefundNo, refundOrder.getMchRefundNo());
        }
        if (refundOrder.getState() != null) {
            queryWrapper.eq(RefundOrderEntity::getState, refundOrder.getState());
        }
        if (StringUtils.isNotEmpty(refundOrder.getAppId())) {
            queryWrapper.eq(RefundOrderEntity::getAppId, refundOrder.getAppId());
        }
        if (paramJSON != null) {
            if (StringUtils.isNotEmpty(paramJSON.getString("createdStart"))) {
                queryWrapper.ge(RefundOrderEntity::getCreatedAt, paramJSON.getString("createdStart"));
            }
            if (StringUtils.isNotEmpty(paramJSON.getString("createdEnd"))) {
                queryWrapper.le(RefundOrderEntity::getCreatedAt, paramJSON.getString("createdEnd"));
            }
        }
        // 三合一订单
        if (paramJSON != null && StringUtils.isNotEmpty(paramJSON.getString("unionOrderId"))) {
            queryWrapper.and(wr -> {
                wr.eq(RefundOrderEntity::getPayOrderId, paramJSON.getString("unionOrderId"))
                        .or().eq(RefundOrderEntity::getRefundOrderId, paramJSON.getString("unionOrderId"))
                        .or().eq(RefundOrderEntity::getChannelPayOrderNo, paramJSON.getString("unionOrderId"))
                        .or().eq(RefundOrderEntity::getMchRefundNo, paramJSON.getString("unionOrderId"));
            });
        }
        queryWrapper.orderByDesc(RefundOrderEntity::getCreatedAt);

        return page(iPage, queryWrapper);
    }

    /**
     * 更新退款单状态  【退款中】 --》 【退款成功】
     **/
    @Transactional
    public boolean updateIng2Success(String refundOrderId, String channelOrderNo) {
        RefundOrderEntity updateOrder = new RefundOrderEntity();
        updateOrder.setState(RefundOrderEntity.STATE_SUCCESS);
        updateOrder.setChannelOrderNo(channelOrderNo);
        updateOrder.setSuccessTime(new Date());

        // 1. 更新退款订单数据
        if (!update(updateOrder, new LambdaUpdateWrapper<RefundOrderEntity>()
                .eq(RefundOrderEntity::getRefundOrderId, refundOrderId)
                .eq(RefundOrderEntity::getState, RefundOrderEntity.STATE_ING))) {
            return false;
        }

        // 2. 更新订单表数据（更新退款次数,退款状态,如全额退款更新支付状态为已退款）
        RefundOrderEntity refundOrder = getOne(new LambdaQueryWrapper<RefundOrderEntity>()
                .select(RefundOrderEntity::getPayOrderId, RefundOrderEntity::getRefundAmount)
                .eq(RefundOrderEntity::getRefundOrderId, refundOrderId));
        int updateCount =
                payOrderDao.updateRefundAmountAndCount(refundOrder.getPayOrderId(), refundOrder.getRefundAmount());

        if (updateCount <= 0) {
            throw new BizException("更新订单数据异常");
        }

        return true;
    }
}